package rest

import (
	"net/http"
	"strconv"

	"bmember/internal/object"

	"github.com/labstack/echo/v4"
	"github.com/pkg/errors"

	"bmember/internal/conf"
	"bmember/internal/service"
	"bmember/pkg/log"
	"bmember/pkg/lueerror"
	"bmember/pkg/util"
)

type Base struct {
	logger log.Factory
	cfg    *conf.Config
}

var base *Base

func InitRestBase(logger log.Factory, cfg *conf.Config) {
	base = &Base{
		logger: logger,
		cfg:    cfg,
	}
}

// ParseBody 请求 body 解析
func (b *Base) ParseBody(c echo.Context, model interface{}) lueerror.LueError {
	if err := c.Bind(model); err != nil {
		return lueerror.InvalidRequest(err)
	}
	if errV := c.Validate(model); errV != nil {
		return lueerror.InvalidRequest(errV)
	}
	return nil
}

type httpResp struct {
	Code    string      `json:"code"`
	Detail  string      `json:"detail"`
	Msg     string      `json:"msg"`
	Data    interface{} `json:"data"`
	Success bool        `json:"success"`
}

// SimpleRet simple http return
func (b *Base) SimpleRet(c echo.Context, ret interface{}, errL lueerror.LueError) error {
	if errL != nil {
		return errL
	}
	resp := &httpResp{
		Code:    "10000",
		Detail:  "",
		Msg:     "",
		Data:    ret,
		Success: true,
	}
	return c.JSON(http.StatusOK, resp)
}

func (b *Base) MobileCheck(mobile string) lueerror.LueError {
	if !util.CNMobile(mobile) {
		return lueerror.InvalidMobile(errors.New("手机号格式错误"))
	}
	return nil
}

func (b *Base) EmailCheck(email string) lueerror.LueError {
	if !util.Email(email) {
		return lueerror.InvalidEmail(errors.New("邮箱格式错误"))
	}
	return nil
}

func (b *Base) EmailMobileCheck(email, mobile string) lueerror.LueError {
	if email != "" {
		errL := b.EmailCheck(email)
		if errL != nil {
			return errL
		}
	}
	if mobile != "" {
		errL := b.MobileCheck(mobile)
		if errL != nil {
			return errL
		}
	}
	return nil
}

// VerifyJwtToken jwt token 校验
func (b *Base) VerifyJwtToken(c echo.Context) (*service.JwtPayload, lueerror.LueError) {
	token := c.Request().Header.Get("Authorization")
	return service.GetService().VerifyToken(token)
}

// AdminPermissionCheck admin 后台权限检查
func (b *Base) AdminPermissionCheck(c echo.Context, permission string) (*object.AdminToken, lueerror.LueError) {
	token := c.Request().Header.Get("B-Token")
	if token == "" {
		return nil, lueerror.HasNoPermission()
	}
	hasPerm, empInfo, errL := service.GetService().AdminPermissionCheck(c.Request().Context(), token, permission)
	if errL != nil {
		return nil, errL
	}
	if !hasPerm {
		return nil, lueerror.HasNoPermission()
	}
	return empInfo, nil
}

// 解析分页逻辑
func paginationParse(c echo.Context) object.Pagination {
	pageNo := c.QueryParam("page_no")
	pageSize := c.QueryParam("page_size")
	pg := object.NewPagination(0, 0)
	pg.ParsePageNo(pageNo)
	pg.ParsePageSize(pageSize)
	return pg
}

// 解析 int64 query 参数
func parseInt64Query(c echo.Context, key string) (int64, lueerror.LueError) {
	val := c.QueryParam(key)
	if val == "" {
		return 0, nil
	}
	ret, err := strconv.ParseInt(val, 10, 64)
	if err != nil {
		return 0, lueerror.InvalidRequest(err)
	}
	return ret, nil
}
